package com.ccplay.dataservice.web.payment;

import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import com.ccplay.dataservice.dto.OrderPaymentChannelDto;
import com.ccplay.dataservice.dto.WeixinOrderNotifyDto;
import com.ccplay.dataservice.web.BaseAction;
import com.google.gson.reflect.TypeToken;
import com.oxygen.constants.Constant;
import com.oxygen.dto.ApiFinalResponse;
import com.oxygen.enums.ApiMethodEnum;
import com.oxygen.util.JsonUtil;
import com.oxygen.util.MapUtil;
import com.oxygen.util.Md5Util;
import com.oxygen.util.StringUtil;
import com.oxygen.util.XmlUtil;
import com.oxygen.web.WebHelper;

@Controller
@RequestMapping(value = { "/api/v2/payment" })
public class WexinpayCallbackAction extends BaseAction {

	private static final Logger loger = Logger.getLogger(WexinpayCallbackAction.class);

	public static void main(String[] args) {
		String wxNotifyXml = "<xml><appid><![CDATA[wx72232c8283720917]]></appid><bank_type><![CDATA[CFT]]></bank_type><cash_fee><![CDATA[1]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[N]]></is_subscribe><mch_id><![CDATA[1237851002]]></mch_id><nonce_str><![CDATA[pf6pp63u58o5az2smb74osdegsibs4sv]]></nonce_str><openid><![CDATA[oeAEys4H_7kSz2ZjgAHrx68OOboc]]></openid><out_trade_no><![CDATA[2016013111013862526216018]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[16821758211F5A09F3C9D6FA5BE6D9F2]]></sign><time_end><![CDATA[20160131110146]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[APP]]></trade_type><transaction_id><![CDATA[1005330916201601313007851885]]></transaction_id></xml>";
		WeixinOrderNotifyDto wxNotifyDto = (WeixinOrderNotifyDto) XmlUtil.xmlToObject(wxNotifyXml, WeixinOrderNotifyDto.class);
		System.out.println(wxNotifyDto);
		Map<String, Object> wxNotifyMap = MapUtil.objectToMap(wxNotifyDto);
		System.out.println(wxNotifyMap);
		String rightSign = new WexinpayCallbackAction()._sign(wxNotifyMap, "MIICdwIBADANBgkqhkiG9w0BAQEFAASC");
		System.out.println("rightSign=" + rightSign + " inputSign=" + wxNotifyDto.getSign());
	}

	/**
	 * 微信支付回调
	 * 
	 * @param req
	 * @param rsp
	 * @return
	 */
	@RequestMapping(value = { "/weixinpayCallback/{paymentId}", "/weixinpayCallback/{paymentId}/" })
	public String weixinpayCallback(@PathVariable String paymentId, HttpServletRequest req, HttpServletResponse rsp) {
		String wxNotifyXml = WebHelper.getHttpBody(req);
		loger.info("paymentId=" + paymentId + " wxNotifyXml=" + wxNotifyXml);
		WeixinOrderNotifyDto wxNotifyDto = (WeixinOrderNotifyDto) XmlUtil.xmlToObject(wxNotifyXml, WeixinOrderNotifyDto.class);
		if (wxNotifyDto != null && !StringUtils.isEmpty(wxNotifyDto.getSign())) {
			// 验签
			Map<String, Object> wxNotifyMap = MapUtil.objectToMap(wxNotifyDto);
			String rightSign = this._sign(wxNotifyMap, this.weixinpay_key);
			if (wxNotifyDto.getSign().equals(rightSign)) {
				loger.info("weixinpayCallback验证签名结果[成功].");
				// 检查结果
				if ("SUCCESS".equals(wxNotifyDto.getReturn_code())) {
					// ////////////////////////////////////////////////////////////////////////////////////////
					Map<String, Object> appendMap = new HashMap<String, Object>();
					appendMap.put(Constant.API_KEY, "android_payment_sdk");
					appendMap.put("paymentDesc", wxNotifyXml);
					appendMap.put("paymentChannelCode", "weixinpay");
					appendMap.put("transaction_no", wxNotifyDto.getOut_trade_no());
					appendMap.put("paymentId", paymentId);
					appendMap.put("paymentTransactionNo", wxNotifyDto.getTransaction_id());
					if ("SUCCESS".equals(wxNotifyDto.getResult_code())) {
						appendMap.put("status", "paid");
					} else {
						appendMap.put("status", "pay_fail");
					}
					this.callApi(ApiMethodEnum.PAYMENT_PAYMENTCALLBACK, appendMap);
					return this._outputNotifyResponse("SUCCESS", "OK", rsp);
					// //////////////////////////////////////////////////////////////////////////////////////
				} else {
					return this._outputNotifyResponse("FAIL", "接收失败", rsp);
				}
			} else {
				loger.info("weixinpayCallback验证签名结果[成功].");
				return this._outputNotifyResponse("FAIL", "签名失败", rsp);
			}
		}
		return this._outputNotifyResponse("FAIL", "参数格式校验错误", rsp);
	}

	
	
	
	@RequestMapping(value = { "/v2/weixinpayCallback/{paymentId}", "/v2/weixinpayCallback/{paymentId}/" })
	public String weixinpayCallbackForV2(@PathVariable String paymentId, HttpServletRequest req, HttpServletResponse rsp) {
		String wxNotifyXml = WebHelper.getHttpBody(req);
		loger.info("paymentId=" + paymentId + " wxNotifyXml=" + wxNotifyXml);
		WeixinOrderNotifyDto wxNotifyDto = (WeixinOrderNotifyDto) XmlUtil.xmlToObject(wxNotifyXml, WeixinOrderNotifyDto.class);
		if (wxNotifyDto != null && !StringUtils.isEmpty(wxNotifyDto.getSign())) {
			// 验签
			Map<String, Object> wxNotifyMap = MapUtil.objectToMap(wxNotifyDto);
			String rightSign = this._sign(wxNotifyMap, this.weixinpay_key_v2);
			if (wxNotifyDto.getSign().equals(rightSign)) {
				loger.info("weixinpayCallback验证签名结果[成功].");
				// 检查结果
				if ("SUCCESS".equals(wxNotifyDto.getReturn_code())) {
					// ////////////////////////////////////////////////////////////////////////////////////////
					Map<String, Object> appendMap = new HashMap<String, Object>();
					appendMap.put(Constant.API_KEY, "android_payment_sdk");
					appendMap.put("paymentDesc", wxNotifyXml);
					appendMap.put("paymentChannelCode", "weixinpay");
					appendMap.put("transaction_no", wxNotifyDto.getOut_trade_no());
					appendMap.put("paymentId", paymentId);
					appendMap.put("paymentTransactionNo", wxNotifyDto.getTransaction_id());
					if ("SUCCESS".equals(wxNotifyDto.getResult_code())) {
						appendMap.put("status", "paid");
					} else {
						appendMap.put("status", "pay_fail");
					}
					this.callApi(ApiMethodEnum.PAYMENT_PAYMENTCALLBACK, appendMap);
					return this._outputNotifyResponse("SUCCESS", "OK", rsp);
					// //////////////////////////////////////////////////////////////////////////////////////
				} else {
					return this._outputNotifyResponse("FAIL", "接收失败", rsp);
				}
			} else {
				loger.info("weixinpayCallback验证签名结果[成功].");
				return this._outputNotifyResponse("FAIL", "签名失败", rsp);
			}
		}
		return this._outputNotifyResponse("FAIL", "参数格式校验错误", rsp);
	}
	
	
	
	

	@RequestMapping(value = { "/m/weixinpayCallback/{paymentId}", "/m/weixinpayCallback/{paymentId}/" })
	public String weixinpayCallbackForM(@PathVariable String paymentId, HttpServletRequest req, HttpServletResponse rsp) {
		String wxNotifyXml = WebHelper.getHttpBody(req);
		loger.info("paymentId=" + paymentId + " wxNotifyXml=" + wxNotifyXml);
		WeixinOrderNotifyDto wxNotifyDto = (WeixinOrderNotifyDto) XmlUtil.xmlToObject(wxNotifyXml, WeixinOrderNotifyDto.class);
		if (wxNotifyDto != null && !StringUtils.isEmpty(wxNotifyDto.getSign())) {
			// 验签
			Map<String, Object> wxNotifyMap = MapUtil.objectToMap(wxNotifyDto);
			String rightSign = this._sign(wxNotifyMap, this.weixinpay_key_m);
			loger.info("签名对比rightSign="+rightSign+","+wxNotifyDto.getSign());
			if (wxNotifyDto.getSign().equals(rightSign)) {
				loger.info("weixinpayCallback验证签名结果[成功].");
				// 检查结果
				if ("SUCCESS".equals(wxNotifyDto.getReturn_code())) {
					// ////////////////////////////////////////////////////////////////////////////////////////
					Map<String, Object> appendMap = new HashMap<String, Object>();
					appendMap.put(Constant.API_KEY, "android_payment_sdk");
					appendMap.put("paymentDesc", wxNotifyXml);
					appendMap.put("paymentChannelCode", "weixinpay");
					appendMap.put("transaction_no", wxNotifyDto.getOut_trade_no());
					appendMap.put("paymentId", paymentId);
					appendMap.put("paymentTransactionNo", wxNotifyDto.getTransaction_id());
					if ("SUCCESS".equals(wxNotifyDto.getResult_code())) {
						appendMap.put("status", "paid");
					} else {
						appendMap.put("status", "pay_fail");
					}
					this.callApi(ApiMethodEnum.PAYMENT_PAYMENTCALLBACK, appendMap);
					return this._outputNotifyResponse("SUCCESS", "OK", rsp);
					// //////////////////////////////////////////////////////////////////////////////////////
				} else {
					return this._outputNotifyResponse("FAIL", "接收失败", rsp);
				}
			} else {
				loger.info("weixinpayCallback验证签名结果[失败].");
				return this._outputNotifyResponse("FAIL", "签名失败", rsp);
			}
		}
		return this._outputNotifyResponse("FAIL", "参数格式校验错误", rsp);
	}
	
	
	
	
	
	
	private String _outputNotifyResponse(String returnCode, String returnMsg, HttpServletResponse rsp) {
		StringBuffer str = new StringBuffer();
		str.append("<xml>");
		str.append("<return_code><![CDATA[" + returnCode + "]]></return_code>");
		str.append("<return_msg><![CDATA[" + returnMsg + "]]></return_msg>");
		str.append("</xml>");
		return WebHelper.outputXml(str.toString(), rsp);
	}

	private String _sign(Map<String, Object> paramMap, String apiSecret) {
		Map<String, Object> signMap = new TreeMap<String, Object>();
		signMap.putAll(paramMap);
		StringBuffer str = new StringBuffer();
		for (Entry<String, Object> entry : signMap.entrySet()) {
			String key = entry.getKey();
			if ("sign".equals(key)) {
				continue;
			}
			Object value = entry.getValue();
			if (value != null && !"".equals(value.toString().trim()) && !"null".equals(value.toString())) {
				str.append(key);
				str.append("=");
				str.append(value.toString());
				str.append("&");
			}
		}
		str.append("key=" + apiSecret);
		return Md5Util.encodeString(str.toString()).toUpperCase();
	}
	
	
	public Map<String, Object> queryByPaymentId(String paymentId) {
		Map<String, Object> inMap =new HashMap<String, Object>();
//		inMap.put("paymentId", paymentId);
//		String json = this.callApi(ApiMethodEnum.PAYMENT_QUERYBYPAYMENTID, inMap);
//		loger.info("查询结果json"+json);
//		String prepayId="";
//		if (!StringUtil.isEmpty(json)) {
//			Type type = new TypeToken<Map<String, ApiFinalResponse<OrderPaymentChannelDto>>>() {
//			}.getType();
//			Map<String, ApiFinalResponse<OrderPaymentChannelDto>> retMap = JsonUtil.jsonToObject(json, type);
//			if (retMap != null && retMap.get(ApiMethodEnum.PAYMENT_QUERYBYPAYMENTID.getCode()) != null) {
//				OrderPaymentChannelDto dto=retMap.get(ApiMethodEnum.PAYMENT_QUERYBYPAYMENTID.getCode()).getResults();
//				Type types = new TypeToken<Map<String,String>>() {}.getType();
//				Map<String,String> maps=JsonUtil.jsonToObject(dto.getPayResultMsg(), types);
//				loger.info("数据库查询结果={}"+maps);
//				prepayId=maps.get("package");
//				inMap.put("package", prepayId);
//				inMap.put("timeStamp", maps.get("timeStamp"));
//				loger.info("prepayid==》"+maps.get("package"));
//				return  inMap;
//			}
//			}
//		loger.info("支付查询为空");
		return null;
	}
	
	
}
